<template>
  <div class="rtsp-player">
    <div class="controls">
      <div class="input-group">
        <label for="room-id">房间ID:</label>
        <input id="room-id" v-model="roomId" type="text" placeholder="输入房间ID (如: camera1, camera2...)" :disabled="isConnecting || isStreaming" />
      </div>

      <div class="input-group">
        <label for="rtsp-url">RTSP 流地址:</label>
        <input id="rtsp-url" v-model="rtspUrl" type="text" placeholder="rtsp://example.com/stream" :disabled="isConnecting || isStreaming" />
      </div>

      <div class="button-group">
        <button @click="startStream" :disabled="isConnecting || isStreaming || !rtspUrl || !roomId" class="btn btn-primary">
          {{ isConnecting ? "连接中..." : "开始播放" }}
        </button>

        <button @click="stopStream" :disabled="!isStreaming" class="btn btn-secondary">停止播放</button>
      </div>
    </div>

    <div class="status">
      <div class="status-item">
        <span class="label">连接状态:</span>
        <span :class="['status-value', connectionStatus.toLowerCase()]">
          {{ connectionStatus }}
        </span>
      </div>

      <div class="status-item" v-if="streamInfo.videoProducerId">
        <span class="label">视频流ID:</span>
        <span class="status-value">{{ streamInfo.videoProducerId }}</span>
      </div>
    </div>

    <div class="video-container">
      <video ref="videoElement" autoplay muted playsinline controls :style="{ display: isStreaming ? 'block' : 'none' }" @loadstart="onVideoLoadStart" @loadeddata="onVideoLoadedData" @canplay="onVideoCanPlay" @playing="onVideoPlaying" @error="onVideoError" @waiting="onVideoWaiting"></video>

      <div v-if="!isStreaming" class="placeholder">
        <p>请输入RTSP流地址并点击开始播放</p>
      </div>

      <div v-if="isStreaming && !videoPlaying" class="loading">
        <p>视频加载中...</p>
      </div>
    </div>

    <div class="logs" v-if="logs.length > 0">
      <h3>日志信息</h3>
      <div class="log-container">
        <div v-for="(log, index) in logs" :key="index" :class="['log-item', log.type]">
          <span class="timestamp">{{ log.timestamp }}</span>
          <span class="message">{{ log.message }}</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import { io } from "socket.io-client";
import { Device } from "mediasoup-client";

// 响应式数据
const roomId = ref("camera1"); // 默认房间ID
const rtspUrl = ref("rtsp://admin:dh123456@180.168.64.114:20010/cam/realmonitor?channel=1&subtype=0");
const isConnecting = ref(false);
const isStreaming = ref(false);
const videoPlaying = ref(false);
const connectionStatus = ref("未连接");
const streamInfo = ref({
  videoProducerId: null,
  audioProducerId: null,
});
const logs = ref([]);
const videoElement = ref(null);

// Socket.IO 连接
let socket = null;
let device = null;
let recvTransport = null;
let videoConsumer = null;

// 添加日志
const addLog = (message, type = "info") => {
  logs.value.push({
    timestamp: new Date().toLocaleTimeString(),
    message,
    type,
  });

  // 限制日志数量
  if (logs.value.length > 50) {
    logs.value.shift();
  }
};

// 视频事件处理
const onVideoLoadStart = () => {
  addLog("视频开始加载");
  videoPlaying.value = false;
};

const onVideoLoadedData = () => {
  addLog("视频数据已加载", "success");
};

const onVideoCanPlay = () => {
  addLog("视频可以播放", "success");
};

const onVideoPlaying = () => {
  addLog("视频开始播放", "success");
  videoPlaying.value = true;
};

const onVideoError = (event) => {
  const error = event.target.error;
  addLog(`视频播放错误: ${error ? error.message : "未知错误"}`, "error");
  videoPlaying.value = false;
};

const onVideoWaiting = () => {
  addLog("视频缓冲中...");
  videoPlaying.value = false;
};

// 初始化 Socket.IO 连接
const initSocket = () => {
  socket = io("http://113.44.10.21:3000");

  socket.on("connect", () => {
    addLog("Socket.IO 连接成功", "success");
    connectionStatus.value = "已连接";
  });

  socket.on("disconnect", () => {
    addLog("Socket.IO 连接断开", "warning");
    connectionStatus.value = "已断开";
  });

  socket.on("rtsp-stream-started", (data) => {
    addLog(`RTSP 流已启动: ${JSON.stringify(data)}`, "success");
    streamInfo.value = data;
    if (data.videoProducerId) {
      consumeStream(data.videoProducerId);
    }
  });

  socket.on("rtsp-stream-stopped", () => {
    addLog("RTSP 流已停止", "warning");
    stopStream();
  });

  socket.on("consumer-closed", (data) => {
    addLog(`Consumer 已关闭: ${data.consumerId}`, "warning");
  });
};

// 开始播放流
const startStream = async () => {
  if (!rtspUrl.value) {
    addLog("请输入 RTSP 流地址", "error");
    return;
  }

  try {
    isConnecting.value = true;
    videoPlaying.value = false;
    addLog(`开始连接 RTSP 流: ${rtspUrl.value}`);

    // 确保Socket已连接
    if (!socket || !socket.connected) {
      addLog("Socket未连接，正在重新连接...");
      await waitForSocketConnection();
    }

    // 加入房间
    await joinRoom();

    // 启动 RTSP 流
    await startRTSPStream();
  } catch (error) {
    addLog(`连接失败: ${error.message}`, "error");
    isConnecting.value = false;
    isStreaming.value = false;
  }
};

// 等待Socket连接
const waitForSocketConnection = () => {
  return new Promise((resolve, reject) => {
    if (socket && socket.connected) {
      resolve();
      return;
    }

    const timeout = setTimeout(() => {
      reject(new Error("Socket连接超时"));
    }, 10000);

    socket.on("connect", () => {
      clearTimeout(timeout);
      resolve();
    });

    socket.on("connect_error", (error) => {
      clearTimeout(timeout);
      reject(error);
    });
  });
};

// 加入房间
const joinRoom = () => {
  return new Promise((resolve, reject) => {
    socket.emit("join-room", { roomId: roomId.value }, async (response) => {
      if (response.success) {
        addLog("成功加入房间", "success");

        // 初始化 mediasoup device
        try {
          await initializeDevice(response.rtpCapabilities);
          resolve(response);
        } catch (error) {
          addLog(`初始化设备失败: ${error.message}`, "error");
          reject(error);
        }
      } else {
        reject(new Error(response.error));
      }
    });
  });
};

// 初始化 mediasoup device
const initializeDevice = async (rtpCapabilities) => {
  addLog("初始化 mediasoup 设备...");

  device = new Device();

  await device.load({ routerRtpCapabilities: rtpCapabilities });

  addLog(`设备初始化成功 - 支持的编解码器: ${device.rtpCapabilities.codecs.length}`, "success");
};

// 启动 RTSP 流
const startRTSPStream = () => {
  return new Promise((resolve, reject) => {
    socket.emit(
      "start-rtsp-stream",
      {
        rtspUrl: rtspUrl.value,
        roomId: roomId.value,
      },
      (response) => {
        if (response.success) {
          addLog("RTSP 流启动成功", "success");
          isConnecting.value = false;
          isStreaming.value = true;
          connectionStatus.value = "播放中";
          resolve(response);
        } else {
          reject(new Error(response.error));
        }
      }
    );
  });
};

// 消费流
const consumeStream = async (producerId) => {
  try {
    addLog(`开始消费视频流: ${producerId}`);

    if (!device) {
      throw new Error("设备未初始化");
    }

    // 创建接收 Transport
    await createRecvTransport();

    // 创建 Consumer
    await createConsumer(producerId);
  } catch (error) {
    addLog(`消费流失败: ${error.message}`, "error");
  }
};

// 创建接收 Transport
const createRecvTransport = () => {
  return new Promise((resolve, reject) => {
    addLog("创建接收 Transport...");

    socket.emit("create-transport", { direction: "recv" }, async (response) => {
      if (response.success) {
        try {
          const transportOptions = response.transportOptions;

          recvTransport = device.createRecvTransport(transportOptions);

          // 监听 Transport 事件
          recvTransport.on("connect", ({ dtlsParameters }, callback, errback) => {
            addLog("连接 Transport...");

            socket.emit(
              "connect-transport",
              {
                transportId: recvTransport.id,
                dtlsParameters,
              },
              (response) => {
                if (response.success) {
                  addLog("Transport 连接成功", "success");
                  callback();
                } else {
                  addLog(`Transport 连接失败: ${response.error}`, "error");
                  errback(new Error(response.error));
                }
              }
            );
          });

          recvTransport.on("connectionstatechange", (state) => {
            addLog(`Transport 连接状态: ${state}`);
          });

          addLog("接收 Transport 创建成功", "success");
          resolve();
        } catch (error) {
          addLog(`创建 Transport 失败: ${error.message}`, "error");
          reject(error);
        }
      } else {
        reject(new Error(response.error));
      }
    });
  });
};

// 创建 Consumer
const createConsumer = (producerId) => {
  return new Promise((resolve, reject) => {
    addLog(`创建 Consumer: ${producerId}`);

    socket.emit(
      "consume",
      {
        transportId: recvTransport.id,
        producerId: producerId,
        rtpCapabilities: device.rtpCapabilities,
        roomId: roomId.value,
      },
      async (response) => {
        if (response.success) {
          try {
            const { consumerId, rtpParameters, kind } = response;

            videoConsumer = await recvTransport.consume({
              id: consumerId,
              producerId: producerId,
              kind: kind,
              rtpParameters: rtpParameters,
            });

            // 监听 Consumer 事件
            videoConsumer.on("transportclose", () => {
              addLog("Consumer transport 关闭", "warning");
            });

            // 监听 Consumer track 事件
            videoConsumer.on("trackended", () => {
              addLog("Consumer track 结束", "warning");
            });

            // 监听 Consumer 统计信息
            videoConsumer.on("score", (score) => {
              addLog(`Consumer 质量评分: ${JSON.stringify(score)}`);
            });

            // 检查 Consumer 状态
            addLog(`Consumer 创建完成: paused=${videoConsumer.paused}, closed=${videoConsumer.closed}`);

            // 获取媒体流并显示
            const track = videoConsumer.track;
            addLog(`获取到视频轨道: ${track.kind}, readyState: ${track.readyState}, enabled: ${track.enabled}`);

            const stream = new MediaStream();
            stream.addTrack(track);

            addLog(`创建媒体流，轨道数量: ${stream.getTracks().length}, active: ${stream.active}`);

            if (videoElement.value) {
              videoElement.value.srcObject = stream;
              addLog("视频流已连接到播放器", "success");

              // 监听更多视频事件
              videoElement.value.addEventListener('loadedmetadata', () => {
                addLog(`视频元数据加载完成: ${videoElement.value.videoWidth}x${videoElement.value.videoHeight}`, "success");
              });

              // 强制播放
              try {
                await videoElement.value.play();
                addLog("视频播放已启动", "success");
              } catch (playError) {
                addLog(`视频播放失败: ${playError.message}`, "error");
                // 尝试静音播放
                try {
                  videoElement.value.muted = true;
                  await videoElement.value.play();
                  addLog("静音播放成功", "success");
                } catch (mutedPlayError) {
                  addLog(`静音播放也失败: ${mutedPlayError.message}`, "error");
                }
              }
            }

            // 恢复 Consumer - 添加延迟确保所有设置完成
            setTimeout(() => {
              addLog("准备恢复 Consumer...");
              socket.emit("resume-consumer", { consumerId }, (response) => {
                if (response.success) {
                  addLog("Consumer 已恢复播放", "success");
                  resolve();
                } else {
                  addLog(`恢复 Consumer 失败: ${response.error}`, "error");
                  reject(new Error(response.error));
                }
              });
            }, 100);

            // 添加超时处理
            setTimeout(() => {
              addLog("Consumer 恢复超时，尝试强制播放", "warning");
              resolve();
            }, 8000);
          } catch (error) {
            addLog(`创建 Consumer 失败: ${error.message}`, "error");
            reject(error);
          }
        } else {
          reject(new Error(response.error));
        }
      }
    );
  });
};

// 停止播放流
const stopStream = async () => {
  try {
    addLog("停止播放流");

    // 清理 Consumer
    if (videoConsumer) {
      videoConsumer.close();
      videoConsumer = null;
      addLog("Consumer 已关闭");
    }

    // 清理 Transport
    if (recvTransport) {
      recvTransport.close();
      recvTransport = null;
      addLog("Transport 已关闭");
    }

    if (socket) {
      socket.emit("stop-rtsp-stream", { roomId: roomId.value }, (response) => {
        if (response.success) {
          addLog("RTSP 流已停止", "success");
        }
      });
    }

    // 重置状态
    isStreaming.value = false;
    isConnecting.value = false;
    connectionStatus.value = "已停止";
    streamInfo.value = {
      videoProducerId: null,
      audioProducerId: null,
    };

    // 清空视频元素
    if (videoElement.value) {
      videoElement.value.srcObject = null;
    }
  } catch (error) {
    addLog(`停止流失败: ${error.message}`, "error");
  }
};

// 组件挂载
onMounted(() => {
  addLog("RTSP 播放器初始化");
  initSocket();
});

// 组件卸载
onUnmounted(() => {
  if (socket) {
    socket.disconnect();
  }
});
</script>

<style scoped>
.rtsp-player {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.controls {
  background: #f5f5f5;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
}

.input-group {
  margin-bottom: 15px;
}

.input-group label {
  display: block;
  margin-bottom: 5px;
  font-weight: bold;
}

.input-group input {
  width: 100%;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
}

.button-group {
  display: flex;
  gap: 10px;
}

.btn {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s;
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.btn-primary {
  background-color: #007bff;
  color: white;
}

.btn-primary:hover:not(:disabled) {
  background-color: #0056b3;
}

.btn-secondary {
  background-color: #6c757d;
  color: white;
}

.btn-secondary:hover:not(:disabled) {
  background-color: #545b62;
}

.status {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
  padding: 15px;
  background: #e9ecef;
  border-radius: 4px;
}

.status-item {
  display: flex;
  align-items: center;
  gap: 8px;
}

.label {
  font-weight: bold;
}

.status-value {
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
}

.status-value.已连接,
.status-value.播放中 {
  background-color: #d4edda;
  color: #155724;
}

.status-value.未连接,
.status-value.已断开,
.status-value.已停止 {
  background-color: #f8d7da;
  color: #721c24;
}

.video-container {
  background: #000;
  border-radius: 8px;
  overflow: hidden;
  margin-bottom: 20px;
  min-height: 400px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.video-container video {
  width: 100%;
  height: auto;
  max-height: 600px;
}

.placeholder {
  color: #666;
  text-align: center;
}

.logs {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 15px;
}

.logs h3 {
  margin-top: 0;
  margin-bottom: 15px;
}

.log-container {
  max-height: 300px;
  overflow-y: auto;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  padding: 10px;
  background: white;
}

.log-item {
  display: flex;
  gap: 10px;
  margin-bottom: 5px;
  font-size: 12px;
  font-family: monospace;
}

.timestamp {
  color: #6c757d;
  min-width: 80px;
}

.log-item.success .message {
  color: #28a745;
}

.log-item.error .message {
  color: #dc3545;
}

.log-item.warning .message {
  color: #ffc107;
}
</style>
